

// 1. 发布订阅模式介绍

//    发布---订阅模式又叫观察者模式，它定义了对象间的一种一对多的关系，让多个观察者对象同时监听某一个主题对象，当一个对象发生改变时，所有依赖于它的对象都将得到通知。

//   现实生活中的发布-订阅模式；

// 比如小红最近在淘宝网上看上一双鞋子，但是呢 联系到卖家后，才发现这双鞋卖光了，但是小红对这双鞋又非常喜欢，所以呢联系卖家，问卖家什么时候有货，卖家告诉她，要等一个星期后才有货，卖家告诉小红，要是你喜欢的话，你可以收藏我们的店铺，等有货的时候再通知你，所以小红收藏了此店铺，但与此同时，小明，小花等也喜欢这双鞋，也收藏了该店铺；等来货的时候就依次会通知他们；

// 在上面的故事中，可以看出是一个典型的发布订阅模式，卖家是属于发布者，小红，小明等属于订阅者，订阅该店铺，卖家作为发布者，当鞋子到了的时候，会依次通知小明，小红等，依次使用旺旺等工具给他们发布消息；

// 发布订阅模式的优点：

//   1. 支持简单的广播通信，当对象状态发生改变时，会自动通知已经订阅过的对象。

// 比如上面的列子，小明，小红不需要天天逛淘宝网看鞋子到了没有，在合适的时间点，发布者(卖家)来货了的时候，会通知该订阅者(小红，小明等人)。

//   2. 发布者与订阅者耦合性降低，发布者只管发布一条消息出去，它不关心这条消息如何被订阅者使用，同时，订阅者只监听发布者的事件名，只要发布者的事件名不变，它不管发布者如何改变；同理卖家（发布者）它只需要将鞋子来货的这件事告诉订阅者(买家)，他不管买家到底买还是不买，还是买其他卖家的。只要鞋子到货了就通知订阅者即可。

//  对于第一点，我们日常工作中也经常使用到，比如我们的ajax请求，请求有成功(success)和失败(error)的回调函数，我们可以订阅ajax的success和error事件。我们并不关心对象在异步运行的状态，我们只关心success的时候或者error的时候我们要做点我们自己的事情就可以了~

// 发布订阅模式的缺点：

//   创建订阅者需要消耗一定的时间和内存。

//   虽然可以弱化对象之间的联系，如果过度使用的话，反而使代码不好理解及代码不好维护等等。

// 2. 如何实现发布--订阅模式？

//    1. 首先要想好谁是发布者(比如上面的卖家)。

//    2. 然后给发布者添加一个缓存列表，用于存放回调函数来通知订阅者(比如上面的买家收藏了卖家的店铺，卖家通过收藏了该店铺的一个列表名单)。

//    3. 最后就是发布消息，发布者遍历这个缓存列表，依次触发里面存放的订阅者回调函数。

// 我们还可以在回调函数里面添加一点参数，比如鞋子的颜色，鞋子尺码等信息；

// 我们先来实现下简单的发布-订阅模式；代码如下：

var shoeObj = {}; // 定义发布者
shoeObj.list = []; // 缓存列表 存放订阅者回调函数
        
// 增加订阅者
shoeObj.listen = function(fn) {
    shoeObj.list.push(fn);  // 订阅消息添加到缓存列表
}

// 发布消息
shoeObj.trigger = function(){
    for(var i = 0,fn; fn = this.list[i++];) {
        fn.apply(this,arguments); 
    }
}
// 小红订阅如下消息
shoeObj.listen(function(color,size){
    console.log("颜色是："+color);
    console.log("尺码是："+size);  
});

// 小花订阅如下消息
shoeObj.listen(function(color,size){
    console.log("再次打印颜色是："+color);
    console.log("再次打印尺码是："+size); 
});
shoeObj.trigger("红色",40);
shoeObj.trigger("黑色",42);